package com.baosight.risk.service.fltd.impl;


import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.ws.rs.core.MediaType;

import org.apache.commons.collections.CollectionUtils;
import org.apache.wink.client.ClientConfig;
import org.apache.wink.client.ClientResponse;
import org.apache.wink.client.Resource;
import org.apache.wink.client.RestClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.baosight.iplat4j.core.ei.EiConstant;
import com.baosight.iplat4j.core.ei.EiInfo;
import com.baosight.iplat4j.core.service.soa.XEventManager;
import com.baosight.risk.api.fltd.FltdNoticeService;
import com.baosight.risk.api.fltd.FltdProcessService;
import com.baosight.risk.api.fltd.FltdTaskService;
import com.baosight.risk.api.xtaa.code.IXtaaCodeService;
import com.baosight.risk.base.redis.BaseRedis;
import com.baosight.risk.base.service.BaseServiceImpl;
import com.baosight.risk.common.aspects.factory.AsyncFactory;
import com.baosight.risk.common.bean.BeanUtils;
import com.baosight.risk.common.manager.AsyncManager;
import com.baosight.risk.common.utils.BSWMessageUtils;
import com.baosight.risk.common.utils.DateUtils;
import com.baosight.risk.common.utils.HttpClientUtil;
import com.baosight.risk.common.utils.ReadProperties;
import com.baosight.risk.common.utils.StringUtils;
import com.baosight.risk.mapper.fltd.FltdHistoryMapper;
import com.baosight.risk.mapper.fltd.FltdNoticeMapper;
import com.baosight.risk.mapper.fltd.FltdTaskMapper;
import com.baosight.risk.service.fltd.entity.FltdNotice;
import com.baosight.risk.service.fltd.entity.FltdTask;
import com.baosight.risk.service.fltd.param.FltdNoticeQueryActiveParam;
import com.baosight.risk.service.fltd.vo.BSWMessage;
import com.baosight.risk.service.system.entity.SysOperLog;
import com.baosight.risk.service.xtaa.code.entity.XtaaCode;
import com.google.common.collect.Maps;

import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;

/**
 * 作者： lishaoqing
 * 时间： 2019年11月09日
 * 描述： FltdNoticeServiceImpl
 * 版本: v1.0
 */
@Slf4j
@Service
public class FltdNoticeServiceImpl extends BaseServiceImpl<FltdNotice> implements FltdNoticeService {

    // 测试机 http://10.70.61.10:9081/bmc
//    private static final String MC_URL = "http://10.70.16.203:5932/services/restMessage/{msgNo}/subscriber/{empCode}";

    // 正式机 http://mc.baogang.info/bmc
    private static final String MC_URL = ReadProperties.getValueString("xbus.mcUrl");

    //消息类别
    private final String msgType = ReadProperties.getValueString("xbus.msgType");

    //业务系统访问地址
    private final String url = ReadProperties.getValueString("xbus.url");

    //源系统编码
    private final String sourceCode = ReadProperties.getValueString("xbus.sourceCode");

    private final String FLTD_NOTICE_KEY = "fltd:notice:key:";

    @Autowired
    private BaseRedis baseRedis;

    @Autowired
    private FltdTaskService fltdTaskService;

    @Autowired
    private FltdTaskMapper fltdTaskMapper;

    @Autowired
    private FltdProcessService fltdProcessService;

    @Autowired
    private FltdNoticeMapper fltdNoticeMapper;

    @Autowired
    private FltdHistoryMapper fltdHistoryMapper;
    @Autowired
    private IXtaaCodeService xtaaCodeService;

    @Override
    public void add(String userCode) throws Exception {
        if (!"admin".equals(userCode)){
            String key = FLTD_NOTICE_KEY + userCode;
            //如果redis中没有，添加工号
            if (!baseRedis.isKey(key)) {
                baseRedis.setValue(key, userCode);
            }
        }
    }

    @Override
    public void sendMsg(String userCode, String userName) throws Exception {
        List<SysOperLog> logs = new ArrayList<>();
        Exception error = null;
        try {
            if (StringUtils.isNotEmpty(userCode)) {
                int num = fltdTaskService.selectTaskCount(userCode);
                if (num < 1) {
                    //数据有误
                    closeMessage(userCode);
                } else {
                    //发送待办
                    send(userCode, userName, num);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("OA待办发送失败："+e.getMessage());
        }
    }

    @Override
    public void doSchedule(String jobId) throws Exception {
        List<SysOperLog> logs = new ArrayList<>();
        Exception error = null;
        try {
            //查询所有人的待办
            List<FltdTask> tasks = fltdTaskService.selectAllTaskList();
            if (CollectionUtils.isNotEmpty(tasks)) {
                //从redis获取所有待办的工号
                Set<Object> keys = baseRedis.keys(FLTD_NOTICE_KEY + "*");
                for (Object obj : keys) {
                    String key = (String) obj;
                    if (key != null) {
                        String userCode = (String) baseRedis.getValue(key);
                        if (StringUtils.isNotEmpty(userCode)) {
                            int num = -1;
                            for (FltdTask task : tasks) {
                                if (userCode.equals(task.getCurrUserCode())) {
                                    num = task.getExt1() == null ? 0 : Integer.parseInt(task.getExt1());
                                    if (num == 0) {
                                        //数据有误
                                        closeMessage(userCode);
                                    } else {
                                        //发送待办
                                        send(userCode, task.getCurrUserName(), num);
                                    }
                                    break;
                                }
                            }
                            //没有待办，关闭显示
                            if (num == -1) {
                                closeMessage(userCode);
                            }
                        }
                        //从redis中删除工号
                        baseRedis.delete(key);
                    }
                }
            }
        }catch (Exception e) {
            error = e;
            logs.add(fltdProcessService.getLog("OA待办定时任务执行失败", 1, e.getMessage(), jobId));
        }
        // 保存日志到数据库
        if (CollectionUtils.isNotEmpty(logs)) {
            AsyncManager.me().execute(AsyncFactory.batchRecordOper(logs));
        }
        if (error != null) {
            throw error;
        }
    }

    @Override
    public void send(String userCode, String userName, int num) throws Exception {
        //关闭oa待办
        Boolean deleteOAFlag=closeMessage(userCode);
        if(deleteOAFlag){//判断是否删除完毕,且执行完毕
            //新增oa待办
            insertOA(userCode, userName, num);
        }

    }

    /**
     * 发送OA待办  2020/07/02
     * @throws Exception
     */
    @Override
    public void sendOA(String jobId) throws Exception {

        List<Map> fltdTasks = fltdTaskMapper.selectOpenTask();
        for (Map task:fltdTasks){
            int num=Integer.parseInt( task.get("number").toString());
            //关闭oa待办
            Boolean deleteOAFlag=closeMessage((String) task.get("currUserCode"));
            if(deleteOAFlag){//判断是否删除完毕,且执行完毕
                //新增oa待办
                insertOA((String) task.get("currUserCode"),(String) task.get("currUserName"),num);
            }
            //2021-01-18改变先删后发
           // insertOA((String) task.get("currUserCode"),(String) task.get("currUserName"),num);
        }
    }

    @Override
    public void insertOA(String userCode, String userName, int num) throws Exception {
        String msgNo = BSWMessageUtils.generateMsgNo();
        if(StringUtils.isNotEmpty(msgNo)){
            try {
                // 业务数据
                BSWMessage bean = new BSWMessage();
                bean.setMessageType(msgType);
                bean.setIdentification(BSWMessageUtils.generateIdentification(userCode));
                bean.setSubject("宝钢股份全面风险管理平台您有" + num + "个待办待处理。");
                bean.setUrl(url);
                bean.setFrom("admin");
                bean.setTo("U" + userCode);
                bean.setExpiryDate(DateUtils.plusDays(new Date(), 1));
                bean.setSendSysXbusCode(sourceCode);
                bean.setMsgNo(msgNo);
                // 业务数据组装结束....
                String eventId = "E_BG_MC_001";// E_DPBI01为项目组自定义 事件ID，前提是已关联发送消息服务S_EM_01

                EiInfo outInfo = new EiInfo();
                outInfo.set(EiConstant.eventId, eventId);
                String msg = BSWMessageUtils.getSendMsg(bean);

                outInfo.set("messageBody", msg);
                FltdNotice notice = new FltdNotice();
                BeanUtils.copyBeanProp(notice, bean);
                BeanUtils.initBean(notice);
                notice.setCurrUserCode(userCode);
                notice.setCurrUserName(userName);
                notice.setNumber(num);
                notice.setStatus("active");
                notice.setUpdateBy(null);
                notice.setUpdateTime(null);
                fltdNoticeMapper.insert(notice);
                outInfo = XEventManager.call(outInfo);

                //记录日志
//                FltdHistory fltdHistory = new FltdHistory();
//                BeanUtils.initBean(fltdHistory);
//                fltdHistory.setId(IDGenerator.getIdStr());
//                fltdHistory.setEmpCode(userCode);
//                fltdHistory.setMsgNo(msgNo);
//                fltdHistory.setUrl(url);
//                fltdHistory.setType("insert");
//                fltdHistoryMapper.insert(fltdHistory);

                System.err.println(outInfo);
                log.info("新增oa待办成功！msgNo="+notice.getMsgNo());
            } catch (Exception e) {
//                e.printStackTrace();
                log.error("新增oa待办异常！"+e.getMessage());
                throw new Exception("新增oa待办异常！"+e.getMessage());
            }
        }else{
            throw new Exception("生成待办流水号msgNo异常！msgNo="+msgNo);
        }
    }

    @Override
    public Boolean closeMessage(String userCode) throws Exception {
        ClientConfig clientConfig = new ClientConfig();
        clientConfig.connectTimeout(5000);
        clientConfig.readTimeout(5000);
        Boolean deleteOAFlag=false;
        try {
            //关闭所有活动的待办
        	FltdNoticeQueryActiveParam param = new FltdNoticeQueryActiveParam();
        	param.setCurrUserCode(userCode);
            List<FltdNotice> activeNotices = fltdNoticeMapper.selectActiveNotice(param);
            for (FltdNotice notice : activeNotices) {
                String url = MC_URL.replace("{empCode}", userCode).replace("{msgNo}", notice.getMsgNo());
                RestClient client = new RestClient(clientConfig);
                Resource resource = client.resource(url);
                resource.header("content-type", "application/json");
                resource.accept(MediaType.APPLICATION_JSON);
                ClientResponse restResponse = null;
                restResponse = resource.put("");
                //记录日志
//                FltdHistory fltdHistory = new FltdHistory();
//                BeanUtils.initBean(fltdHistory);
//                fltdHistory.setId(IDGenerator.getIdStr());
//                fltdHistory.setEmpCode(userCode);
//                fltdHistory.setMsgNo(notice.getMsgNo());
//                fltdHistory.setUrl(url);
//                fltdHistory.setType("close");
//                fltdHistoryMapper.insert(fltdHistory);

                if (restResponse.getStatusCode() != 200) {
                    log.error("禁用消息 调用失败,需要重发,返回码:" + restResponse.getStatusCode());
                }else{
                    notice.setStatus("close");
                    log.info("禁用消息 调用成功,返回码:" + restResponse.getMessage());
                }
            }
            //更新状态
            for (FltdNotice notice : activeNotices) {
                fltdNoticeMapper.updateByPrimaryKeySelective(notice);
            }
            deleteOAFlag=true;
        } catch (Exception e) {
            log.error("禁用消息 调用异常,需要重发:" + e.getMessage());
            throw e;
        }
        return deleteOAFlag;
    }

    @Override
    public void doOffset(String jobId) throws Exception {
        ClientConfig clientConfig = new ClientConfig();
        clientConfig.connectTimeout(5000);
        clientConfig.readTimeout(5000);
        RestClient client = new RestClient(clientConfig);
        try {
            List<FltdNotice> fltdNotices = fltdNoticeMapper.selectOffsetNotice();
            for (FltdNotice notice : fltdNotices) {
                String userCode = notice.getCurrUserCode();
                String url = MC_URL.replace("{empCode}", userCode).replace("{msgNo}", notice.getMsgNo());
                Resource resource = client.resource(url);
                resource.header("content-type", "application/json");
                resource.accept(MediaType.APPLICATION_JSON);
                ClientResponse restResponse = null;
                restResponse = resource.put("");
                if (restResponse.getStatusCode() != 200) {
                    log.error("待办补偿机制禁用消息失败,返回码:" + restResponse.getStatusCode());
                }else{
                    notice.setStatus("close");
                    log.info("待办补偿机制禁用消息成功,返回码:" + restResponse.getMessage());
                }
            }
        } catch (Exception e) {
            throw new Exception("OA待办补偿机制执行失败："+ e.getMessage());
        }
    }

	@Override
	public List<FltdNotice> queryActiveNotices(FltdNoticeQueryActiveParam param) {
		servicePage();
		return fltdNoticeMapper.selectActiveNotice(param);
	}
	
	@Override
	public void deleteOAById(String id) throws Exception {
		FltdNotice notice = this.get(id);
		
		String flowid = notice.getFlowId();
		Map<String,Object> map = Maps.newHashMap();
		map.put("syscode","risk");
		map.put("flowid",flowid);
		map.put("userid",notice.getCurrUserCode());
		String jsonData = JSON.toJSONString(map);

		String result = HttpClientUtil.doPostJson(getUrlByDdCode("B"),jsonData);
		JSONObject js = JSONObject.fromObject(result);
		if (!"1".equals(js.getString("operResult"))) {
			System.out.println("oa4.0 delete error:"+js.getString("message"));
		}else{
			notice.setStatus("close");
			fltdNoticeMapper.updateByPrimaryKeySelective(notice);
		}
	}
	
    private String getUrlByDdCode(String ddCode){
    	List<XtaaCode> xtaaCodes = xtaaCodeService.selectDataByDDTypeCode("OA_URL");
    	for(XtaaCode xtaaCode : xtaaCodes){
    		if(ddCode.equals(xtaaCode.getDdCode())){
    			return xtaaCode.getDdDesc();
    		}
    	}
    	return null;
    }
}
